package cn.abcsys.cloud.devops.runtime.service.impl;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;

import cn.abcsys.cloud.devops.runtime.bean.GridBean;
import cn.abcsys.cloud.devops.runtime.bean.Result;
import cn.abcsys.cloud.devops.runtime.common.Common;
import cn.abcsys.cloud.devops.runtime.common.Constant;
import cn.abcsys.cloud.devops.runtime.common.Status;
import cn.abcsys.cloud.devops.runtime.common.SystemConfig;
import cn.abcsys.cloud.devops.runtime.common.Type;
import cn.abcsys.cloud.devops.runtime.core.HostCore;
import cn.abcsys.cloud.devops.runtime.dao.ClusterMapper;
import cn.abcsys.cloud.devops.runtime.dao.EventMapper;
import cn.abcsys.cloud.devops.runtime.dao.HostMapper;
import cn.abcsys.cloud.devops.runtime.entity.Cluster;
import cn.abcsys.cloud.devops.runtime.entity.Event;
import cn.abcsys.cloud.devops.runtime.entity.Host;
import cn.abcsys.cloud.devops.runtime.model.ClusterModel;
import cn.abcsys.cloud.devops.runtime.service.ClusterService;
/**
 * 
 * @author mayunhao
 *	集群管理
 */
@Component
public class ClusterServiceImpl implements ClusterService {
	private static final Logger LOGGER = Logger.getLogger(ClusterServiceImpl.class);
	@Autowired
	private ClusterMapper clusterMapper;
	@Autowired
	private EventMapper eventMapper;
	@Autowired
	private HostCore hostCore;
	@Autowired
	private HostMapper hostMapper;
	@Autowired
	private SystemConfig systemConfig;
	@Override
	public Result createCluster(Cluster cluster) {
		//step1:校验数据
		if(isClusterExist(cluster.getClusterName())){
			return new Result(false, "集群名称["+cluster.getClusterName()+"]已被占用，请重新输入");
		}
		if(null==cluster.getClusterRegistryId()){
			return new Result(false, "请选择镜像仓库");
		}
		Result result = new Result(true, "创建集群成功");
		try {
			String idstr = cluster.getClusterHostId();
			if(StringUtils.isEmpty(idstr)){
				return new Result(false, "请添加集群主机");
			}
			String[] ids = idstr.split(Constant.separator);
			if(ids.length==0){
				return new Result(false, "请添加集群主机");
			}
			if(cluster.getHaEnable()==Status.JUDGE.YES.ordinal()
					&&ids.length<=1){
				return new Result(false, "请添加集群高可用主机");
			}
			if(cluster.getHaEnable()==Status.JUDGE.YES.ordinal()
					&&StringUtils.isEmpty(cluster.getServiceIp())){
				return new Result(false, "请添加集群高可用IP地址");
			}
			//检查集群节点是否已经正在运行，如果正在运行，被认为是已经在其他集群中运行，不允许加入到新的集群中。
			for(String clusterHostId:ids){
				if(StringUtils.isEmpty(clusterHostId)){
					continue;
				}
				result = this.masterRunning(Integer.valueOf(clusterHostId));
				if(result.isSuccess()){
					return new Result(false,result.getMessage());
				}
			}
			List<Host> updateList = new ArrayList<>();
			//对外提供服务的地址
			String service_ip = cluster.getServiceIp();
			//step2:判断是否高可用
			if(cluster.getHaEnable()==Status.JUDGE.YES.ordinal()){
				for(int i=0;i<ids.length;i++){
					Host clusterHost = null;
					String clusterHostId = ids[i];
					try {
						clusterHost = hostMapper.getHostDetail(Integer.valueOf(clusterHostId));
						updateList.add(clusterHost);
					} catch (NumberFormatException e) {
						return new Result(false, "主机ID["+clusterHostId+"]转换异常:"+e.getMessage());
					} catch (SQLException e) {
						return new Result(false, "主机ID["+clusterHostId+"]查询异常:"+e.getMessage());
					}
					if(null==clusterHost){
						return new Result(false, "主机ID["+clusterHostId+"]不存在");
					}
					if(null!=clusterHost.getClusterId()){
						return new Result(false, "主机["+clusterHost.getHostIp()+"]已在其他集群环境中");
					}
					Map<String, String> params = new HashMap<>();
					params.put(""+(i+1), cluster.getServiceIp());
					//step2-1:高可用集群，集群域名配置的是虚拟IP
					result = hostCore.startKube(clusterHost.getHostIp(), Type.HOST.MASTER.name(),params);
					if(!result.isSuccess()){
						return result;
					}
					//step2-2:修改集群域名对应的服务地址
					result = hostCore.addDns(clusterHost.getHostIp(), service_ip, systemConfig.getKubeMasterDns());
					if(!result.isSuccess()){
						return result;
					}
				}
			}else{
				String clusterHostId = ids[0];
				Host clusterHost = null;
				try {
					clusterHost = hostMapper.getHostDetail(Integer.valueOf(clusterHostId));
					updateList.add(clusterHost);
				} catch (NumberFormatException e) {
					return new Result(false, "主机ID["+clusterHostId+"]转换异常:"+e.getMessage());
				} catch (SQLException e) {
					return new Result(false, "主机ID["+clusterHostId+"]查询异常:"+e.getMessage());
				}
				if(null==clusterHost){
					return new Result(false, "主机ID["+clusterHostId+"]不存在");
				}
				if(null!=clusterHost.getClusterId()){
					return new Result(false, "主机["+clusterHost.getHostIp()+"]已在其他集群环境中");
				}
				//serviceIp设置为当前master主机IP
				service_ip = clusterHost.getHostIp();
				cluster.setServiceIp(service_ip);
				//step2-1:非高可用，启动集群master
				result = hostCore.startKube(clusterHost.getHostIp(), Type.HOST.MASTER.name(),null);
				if(!result.isSuccess()){
					return result;
				}
				//step2-2:修改集群域名对应的服务地址
				result = hostCore.addDns(clusterHost.getHostIp(), service_ip, systemConfig.getKubeMasterDns());
				if(!result.isSuccess()){
					return result;
				}
			}
			//step3:将信息加入集群表
			cluster.setClusterType((byte)Type.CLUSTER.KUBERNETES.ordinal());
			cluster.setClusterName(cluster.getClusterName());
			cluster.setClusterCreator(cluster.getClusterCreator());
			cluster.setClusterStatus((byte)Status.COMMON.NORMAL.ordinal());
			int issuccess = clusterMapper.insertCluster(cluster);
			//step4:更新主机集群状态
			for(Host host:updateList){
				host.setClusterId(cluster.getClusterId());
				hostMapper.updateHost(host);
			}
			if(issuccess!=1){
				result = new Result(false, "创建集群失败,原因未知");
				this.createEvent("创建集群["+cluster.getClusterName()+"]失败,原因未知", 
						Common.CLUSTER_CREATE_CHN, Common.FAIL_CHN, cluster.getClusterId(), 
						Type.EVENT_TYPE.CLUSTER.name(),cluster.getClusterCreator());
			}else{
				//更新集群主机的clusterId
				for(Host host:updateList){
					host.setClusterId(cluster.getClusterId());
					hostMapper.updateHost(host);
				}
				this.createEvent(Common.CLUSTER_CREATE_CHN+"["+cluster.getClusterName()+"]"+Common.SUCCESS_CHN, 
						Common.CLUSTER_CREATE_CHN, Common.SUCCESS_CHN, 
						cluster.getClusterId(), Type.EVENT_TYPE.CLUSTER.name(),
						cluster.getClusterCreator());
			}
		} catch (SQLException e) {
			LOGGER.error("创建集群["+cluster.getClusterName()+"]失败:"+e.getMessage());
			this.createEvent("创建集群["+cluster.getClusterName()+"]失败:"+e.getErrorCode(), 
					Common.CLUSTER_CREATE_CHN, Common.FAIL_CHN, cluster.getClusterId(), 
					Type.EVENT_TYPE.CLUSTER.name(),cluster.getClusterCreator());
			result = new Result(false, "创建集群失败："+e.getMessage());
		}
		LOGGER.info("创建成功");
		return result;
	}

	@Override
	public Result updateCluster(Cluster cluster) {
		Result result = new Result(true, "更新集群成功");
		try {
			int issuccess = clusterMapper.updateCluster(cluster);
			if(issuccess!=1){
				result = new Result(false, "更新集群失败,原因未知");
				this.createEvent("更新集群["+cluster.getClusterName()+"]失败,原因未知", 
						Common.CLUSTER_UPDATE_CHN, Common.FAIL_CHN, cluster.getClusterId(), 
						Type.EVENT_TYPE.CLUSTER.name(),cluster.getClusterCreator());
			}else{
				this.createEvent(Common.CLUSTER_UPDATE_CHN+"["+cluster.getClusterName()+"]"+Common.SUCCESS_CHN, 
						Common.CLUSTER_UPDATE_CHN, Common.SUCCESS_CHN, cluster.getClusterId(), 
						Type.EVENT_TYPE.CLUSTER.name(),cluster.getClusterCreator());
			}
			
		} catch (SQLException e) {
			LOGGER.error("更新集群失败:"+e.getMessage());
			this.createEvent("更新集群["+cluster.getClusterName()+"]失败:"+e.getErrorCode(), 
					Common.CLUSTER_UPDATE_CHN, Common.FAIL_CHN, cluster.getClusterId(), 
					Type.EVENT_TYPE.CLUSTER.name(),cluster.getClusterCreator());
			result = new Result(false, "更新集群失败："+e.getMessage());
		}
		return result;
	}

	@Override
	public Result deleteCluster(Integer clusterId) {
		Result result = new Result(true, "移除集群成功");
		try {
			Host host = new Host();
			host.setHostStatus((byte)Status.COMMON.NORMAL.ordinal());
			host.setHostType((byte)Type.HOST.NODE.ordinal());
			host.setClusterId(clusterId);
			List<Host> hosts = hostMapper.selectHostList(host);
			if(hosts.size()>0){
				return new Result(false, "集群中存在运行的节点");
			}
			Cluster cluster = clusterMapper.getClusterDetail(clusterId);
			if(null==cluster){
				return new Result(false, "集群信息不存在，删除失败。");
			}
			String idstr = cluster.getClusterHostId();
			String[] ids = idstr.split(Constant.separator);
			for(String clusterHostId:ids){
				Host clusterHost = null;
				try {
					clusterHost = hostMapper.getHostDetail(Integer.valueOf(clusterHostId));
				} catch (NumberFormatException e) {
					return new Result(false, "主机ID["+clusterHostId+"]转换异常:"+e.getMessage());
				} catch (SQLException e) {
					return new Result(false, "主机ID["+clusterHostId+"]查询异常:"+e.getMessage());
				}
				//step1：如果daemon正在运行。停止kube daemon
				result = hostCore.masterRunning(clusterHost.getHostIp());
				if(result.isSuccess()){
					result = hostCore.stopKube(clusterHost.getHostIp(), Type.HOST.MASTER.name());
					if(!result.isSuccess()){
						LOGGER.error("Stop kube daemon fail");
						this.createEvent("停止集群["+cluster.getClusterName()+"]的kube daemon失败", 
								Common.CLUSTER_REMOVE_CHN, Common.FAIL_CHN, clusterId, 
								Type.EVENT_TYPE.CLUSTER.name(),cluster.getClusterCreator());
					}
				}
				//step2:移除domain
				result = hostCore.removeDns(clusterHost.getHostIp(), systemConfig.getKubeMasterDns());
				if(!result.isSuccess()){
					LOGGER.error("Remove kubemater domain fail");
					this.createEvent("删除集群["+cluster.getClusterName()+"]Dns失败", 
							Common.CLUSTER_REMOVE_CHN, Common.FAIL_CHN, clusterId, 
							Type.EVENT_TYPE.CLUSTER.name(),cluster.getClusterCreator());
				}
				//cluster主机clusterId清空
				clusterHost.setClusterId(null);
				int i = hostMapper.updateHost(clusterHost);
				if(i!=1){
					this.createEvent("集群["+cluster.getClusterName()+"]主机状态更新失败", 
							Common.CLUSTER_REMOVE_CHN, Common.FAIL_CHN, clusterId, 
							Type.EVENT_TYPE.CLUSTER.name(),cluster.getClusterCreator());
					return new Result(false, "集群主机状态更新失败");
				}
			}
			
			
			int issuccess = clusterMapper.deleteCluster(clusterId);
			if(issuccess!=1){
				result = new Result(false, "移除集群["+cluster.getClusterName()+"]失败,原因未知");
				this.createEvent("移除集群["+cluster.getClusterName()+"]失败,原因未知", 
						Common.CLUSTER_REMOVE_CHN, Common.FAIL_CHN, clusterId, 
						Type.EVENT_TYPE.CLUSTER.name(),cluster.getClusterCreator());
			}else{
				this.createEvent(Common.CLUSTER_REMOVE_CHN+"["+cluster.getClusterName()+"]"+Common.SUCCESS_CHN, 
						Common.CLUSTER_REMOVE_CHN, Common.SUCCESS_CHN, clusterId, 
						Type.EVENT_TYPE.CLUSTER.name(),cluster.getClusterCreator());
			}
		} catch (SQLException e) {
			LOGGER.error("移除集群失败:"+e.getMessage());
			result = new Result(false, "移除集群失败："+e.getMessage());
		}
		return result;
	}

	@Override
	public Result getClusterDetail(Integer clusterId) {
		Result result = null;
		try {
			Cluster cluster = clusterMapper.getClusterDetail(clusterId);
			if(null!=cluster){
				result = new Result(true,JSONObject.toJSON(cluster),"success");
			}else{
				result = new Result(false,"未查到相关结果");
			}
		} catch (SQLException e) {
			LOGGER.error("查询集群详情失败:"+e.getMessage());
			result = new Result(false, "查询失败："+e.getMessage());
		}
		return result;
	}

	@Override
	public GridBean getClusterList(ClusterModel clusterModel) {
		int page = clusterModel.getPage();
		int rows = clusterModel.getRows();
		int totalpage = 0;
		Long totalNum = 0l;
		Page<ClusterModel> pageObject = new Page<ClusterModel>();
		try {
			Map<String, Object> map = new HashMap<>();
			map.put("clusterName", clusterModel.getClusterName());
			map.put("clusterStatus", Status.COMMON.NORMAL.ordinal());
			
			PageHelper.startPage(page, rows);
			List<Cluster> clusterList = clusterMapper.selectClusterList(map);
			for(Cluster cluster: clusterList){
				ClusterModel pageModel = new ClusterModel();
				pageModel.setClusterId(cluster.getClusterId());
				pageModel.setClusterName(cluster.getClusterName());
				Host host = new Host();
				host.setClusterId(cluster.getClusterId());
				host.setHostStatus((byte)Status.HOST.OFF.ordinal());
				List<Host> offNum = hostMapper.selectHostList(host);
				host.setHostStatus((byte)Status.HOST.ONLINE.ordinal());
				List<Host> onLineNum = hostMapper.selectHostList(host);
				pageModel.setClusterHostNum(offNum.size()+onLineNum.size());
				pageModel.setClusterHostOffNum(offNum.size());
				pageModel.setClusterHostOnNum(onLineNum.size());
				String[] hostIds = cluster.getClusterHostId().split(Constant.separator);
				JSONArray clusterHostArray = new JSONArray();
				for(String hostId:hostIds){
					Host clusterHost = hostMapper.getHostDetail(Integer.valueOf(hostId));
					clusterHostArray.add(clusterHost);
				}
				pageModel.setClusterHostArray(clusterHostArray);
				pageModel.setClusterHostId(cluster.getClusterHostId());
				pageObject.add(pageModel);
			}
			totalpage = ((Page<?>) clusterList).getPages();
			totalNum = ((Page<?>) clusterList).getTotal();
		} catch (SQLException e) {
			LOGGER.error("批量查询集群失败:"+e.getMessage());
		}
		GridBean gridBean = new GridBean(page, totalpage, totalNum.intValue(), pageObject);
		return gridBean;
	}
	/**
	 * 
	* @Title: createTaskEvent 
	* @Description: 任务执行事件 
	* @param     设定文件 
	* @return void    返回类型 
	* @throws
	 */
	private void createEvent(String eventDesc, String eventName,String eventResult, 
			Integer eventObjectID,String eventType,Integer eventCreator){
		Event event = new Event(eventDesc, eventName, eventResult,eventObjectID, eventType,eventCreator);
		eventMapper.insertEnv(event);
	}
	/**
	* @Title: isClusterExist 
	* @Description: 集群是否已经存在
	* @param @param hostIp
	* @param @return    设定文件 
	* @return boolean    返回类型 
	* @throws
	 */
	public boolean isClusterExist(String clusterName){
		try {
			Map<String, Object> map = new HashMap<>();
			map.put("clusterName", clusterName);
			map.put("clusterStatus", Status.COMMON.NORMAL.ordinal());
			List<Cluster> clusters = clusterMapper.selectClusterList(map);
			if(clusters.isEmpty()){
				return false;
			}else{
				return true;
			}
		} catch (SQLException e) {
			return false;
		}
	}

	@Override
	public GridBean eventList(ClusterModel clusterModel) {
		int page = clusterModel.getPage();
		int rows = clusterModel.getRows();
		int totalpage = 0;
		Long totalNum = 0l;
		Page<Event> pageObject = new Page<Event>();
		PageHelper.startPage(page, rows);
		Event event = new Event();
		event.setEventObjectID(clusterModel.getClusterId());
		event.setEventType(Type.EVENT_TYPE.CLUSTER.name());
		List<Event> events = eventMapper.selectEventByObject(event);
		for(Event temp: events){
			pageObject.add(temp);
		}
		totalpage = ((Page<?>) events).getPages();
		totalNum = ((Page<?>) events).getTotal();
		GridBean gridBean = new GridBean(page, totalpage, totalNum.intValue(), pageObject);
		return gridBean;
	}

	@Override
	public Result listAll(){
		Map<String, Object> map = new HashMap<>();
		map.put("clusterStatus", Status.COMMON.NORMAL.ordinal());
		try {
			List<Cluster> clusterList = clusterMapper.selectClusterList(map);
			return new Result(true, clusterList,"操作成功");
		} catch (SQLException e) {
			return new Result(false, "操作失败："+e.getMessage());
		}
		
	}
	/**
	 * mayunhao
	* @Title: checkMasterKube 
	* @Description: 检查控制节点kube进程是否启动
	* @param @param hostIds
	* @param @param cluster
	* @param @param userId
	* @param @return    设定文件 
	* @return Result    返回类型 
	* @throws
	 */
	private Result masterRunning(Integer clusterHostId) {
		if(null==clusterHostId){
			return new Result(false, "请选择添加主机");
		}
		Host clusterHost = null;
		try {
			clusterHost = hostMapper.getHostDetail(Integer.valueOf(clusterHostId));
		} catch (NumberFormatException e) {
			return new Result(false, "主机ID["+clusterHostId+"]转换异常:"+e.getMessage());
		} catch (SQLException e) {
			return new Result(false, "主机ID["+clusterHostId+"]查询异常:"+e.getMessage());
		}
		if(null==clusterHost){
			return new Result(false, "主机ID["+clusterHostId+"]不存在");
		}
		if(null!=clusterHost.getClusterId()){
			return new Result(false, "主机["+clusterHost.getHostIp()+"]已在其他集群环境中");
		}
		//检查主机kubernetes进程是否已经启动
		Result result = hostCore.masterRunning(clusterHost.getHostIp());
		if(result.isSuccess()){
			return new Result(true, "主机["+clusterHost.getHostIp()+"] master进程已经在运行，不能创建新的集群");
		}
		return new Result(true);
	}
}
